package com.qianfeng.smartplatform.websocket;/*
 *@Description:
 *@author:赵健
 *@Date:zjzzz 2022/9/13 20:25
 */

import com.qianfeng.smartplatform.event.DeviceCommandEvent;
import com.qianfeng.smartplatform.event.DeviceStatusEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Component
public class PowerCommandWebSocket extends TextWebSocketHandler {
    @Autowired
    private ApplicationContext applicationContext;

    private Map<String, WebSocketSession> allClients = new HashMap<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        String path = session.getUri().getPath();
        //最后一位是设备id
        String deviceId = path.substring(path.lastIndexOf("/") + 1);
        //为了方便后面获取deviceId，直接将id设置给会话
        session.getAttributes().put("deviceId", deviceId);
        //以设备的id作为key，将会话保存
        WebSocketSession currentSession = allClients.get(deviceId);
        //如果设备之前有会话，就关闭
        if (currentSession != null && currentSession.isOpen()) {
            currentSession.close();
        }
        //保存会话
        allClients.put(deviceId, session);
        //当设备上线后，我们需要更新设备的状态为在线
        applicationContext.publishEvent(new DeviceStatusEvent(deviceId, DeviceStatusEvent.Status.ONLINE));
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        //如果一个连接关闭了，说明会话结束，应该从allCilent中删除
        String deviceId = (String) session.getAttributes().get("deviceId");
        allClients.remove(deviceId);
        //当设备离线的时候我们需要将设备的状态改成离线
        applicationContext.publishEvent(new DeviceStatusEvent(deviceId, DeviceStatusEvent.Status.OFFLINE));
    }

    @EventListener
    @Async
    public void onCommand(DeviceCommandEvent event) {
        String deviceId = event.getDeviceId();
        //根据设备id获取到会话
        WebSocketSession webSocketSession = allClients.get(deviceId);
        if (webSocketSession != null && webSocketSession.isOpen()) {
            try {
                webSocketSession.sendMessage(new TextMessage(event.getCommand()));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
